/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package analiseSintatica.Regras.Comandos;

import AnaliseLexicaFinal.EstruturaDeDados.LinkToken;
import analiseSintatica.ErroSintaticoException;
import analiseSintatica.Regras.DeclaracoesIniciais.RegraDeclaracao;
import analiseSintatica.Regras.Expressoes.RegraAtribuicao;
import analiseSintatica.Regras.Expressoes.RegraIncremento;
import analiseSintatica.Regras.Funcao.RegraChamadaFuncao;
import analiseSintatica.Regras.Regra;
import analiseSintatica.estruturadados.ErroSintatico;
import analiseSintatica.estruturadados.NoArvore;
import java.util.LinkedList;


/**
 *
 * @author Ivo Romário
 */
public class RegraInstrucao extends Regra{


    protected static Regra instancia;

    protected String estrutura = "<declaracao>|<cmd>|<atribuicao>|<incremento>|<chamada_funcao>;";

    
    /**
     * Construtor privado necessario ao singleton
     */
    public RegraInstrucao(){

    }

    /**
     * Retorna a unica instancia dessa classe.
     * @return
     */
    public static RegraInstrucao getInstance() {
        if (instancia == null) {
            instancia = new RegraInstrucao();
        }
        return (RegraInstrucao) instancia;
    }

    

    @Override
    public NoArvore analisar(LinkedList<LinkToken> listaTokens) throws ErroSintaticoException {

         ErroSintaticoException erros = new ErroSintaticoException();

         NoArvore naoTerminalInstrucao = new NoArvore("<instrucao>", false);

         try{
             if(RegraDeclaracao.getInstance().getPrimeiro().contains(listaTokens.getFirst().getLexema())){
                 naoTerminalInstrucao.adicionaFilho(RegraDeclaracao.getInstance().analisar(listaTokens));
             }
             else if(RegraCmd.getInstance().getPrimeiro().contains(listaTokens.getFirst().getLexema())){
                 naoTerminalInstrucao.adicionaFilho(RegraCmd.getInstance().analisar(listaTokens));
             }
             else if(RegraAtribuicao.getInstance().getPrimeiro().contains(listaTokens.getFirst().getLexema())){
                 naoTerminalInstrucao.adicionaFilho(RegraAtribuicao.getInstance().analisar(listaTokens));
             }
             else if(RegraIncremento.getInstance().getPrimeiro().contains(listaTokens.getFirst().getLexema())){
                 naoTerminalInstrucao.adicionaFilho(RegraIncremento.getInstance().analisar(listaTokens));
             }
             else if(RegraChamadaFuncao.getInstance().getPrimeiro().contains(listaTokens.getFirst().getLexema())){
                 naoTerminalInstrucao.adicionaFilho(RegraChamadaFuncao.getInstance().analisar(listaTokens));
                 
             }

             
         }
         catch(ErroSintaticoException e){
                    while (e.size() != 0) {
                    erros.addErros(e.getErros());
                }
         }

         try{
         naoTerminalInstrucao.adicionaFilho(reconheceLexema(listaTokens, "delimitador", ";",estrutura));
         }
         catch(ErroSintaticoException e){
         }
         if(erros.size() != 0){
            throw erros;
         }

         return naoTerminalInstrucao;
        
    }

    

    @Override
    protected void setPrimeiro() {
        this.primeiro.add("char");
        this.primeiro.add("int");
        this.primeiro.add("float");
        this.primeiro.add("boolean");
        this.primeiro.add("identificador");
        this.primeiro.add("if");
        this.primeiro.add("while");
        this.primeiro.add("do");
        this.primeiro.add("return");
        this.primeiro.add("for");
        this.primeiro.add("printf");
        this.primeiro.add("scanf");
        this.primeiro.add("*");
        this.primeiro.add("++");
        this.primeiro.add("--");
//        this.primeiro = getUniao(this.primeiro, RegraDeclaracao.getInstance().getPrimeiro());
//        this.primeiro = getUniao(this.primeiro, RegraCmd.getInstance().getPrimeiro());
//        this.primeiro = getUniao(this.primeiro, RegraAtribuicao.getInstance().getPrimeiro());
//        this.primeiro = getUniao(this.primeiro, RegraIncremento.getInstance().getPrimeiro());
//        this.primeiro = getUniao(this.primeiro, RegraChamadaFuncao.getInstance().getPrimeiro());
    }

    @Override
    protected void setSeguinte() {
        this.seguinte.add("}");
        this.seguinte = getUniao(this.seguinte, RegraInstrucao.getInstance().getPrimeiro());
        this.seguinte = getUniao(this.seguinte, RegraBloco.getInstance().getSeguinte());
    }

}
